
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.border.LineBorder;

/**
 * La classe CenterPanel estende la classe JPanel ereditandone tutte le sue
 *  proprietà e si occupa di gestire il pannello centrale, suddiviso
 * in 3 pannelli; un pannello dove viene gestito il form per inserire la risposta,
 * un pannello dove viene gestita la frase nascosta e un pannello dove viene mostrato il
 * suggerimento
 * @author Fabio Duma
 */
public class CenterPanel extends JPanel {
    /**
     * oggetto di tipo BoxLayout che imposta il layout del pannello
     */
    private BoxLayout layout;
    /**
     * costante JLabel che visualizza la scritta Risposta
     */
    private final JLabel ANSWER= new JLabel("Risposta");
    /**
     * Oggetto di tipo JTextField per l'inserimento della risposta
     */
    private JTextField answerField;
    /**
     * Oggetto di tipo JButton per l'invio della risposta
     */
    private JButton answerButton;
    /**
     * ArrayList di tipo JLabel contenente la trasposizione grafica all'interno
     * del pannello della frase nascosta 
     */
    private ArrayList<JLabel> phrases=new ArrayList<JLabel>();
    /**
     * Array di tipo stringa contenente le singole parole di una frase
     */
    private String[] phrasesString;
    /**
     * Stringa che identifica la risposta
     */
    private String answer;
    /**
     * Stringa che identifica la frase nascosta
     */
    private String hidephrase;
/**
 * Oggetto List di tipo Player che identifica i giocatori
 */
    private List <Player> players;
    /**
     * Oggetto List di tipo Character contenente i singoli caratteri della frase
     */
    private List<Character> phrasesChar=new ArrayList<Character>();
    /**
     * Lista di tipo Phrase contenete le frasi da indovinare con i relativi suggerimenti
     */
    private List <Phrase> phrasesList;
    
  //  private List <String> saveLetters=new ArrayList<String>();
    /**
     * Lista di tipo JPanel contenente tutti i pannelli disegnati
     */
    List<JPanel> jplist ;
    /**
     * Intero che identifica il numero di manche in corso
     */
    private int manche;
    /**
     * Stringa che identifica il suggerimento della frase in corso
     */
    private String hintString;
    /**
     * Array di tipo Letter che identifica la lista dei pulsanti lettera
     */
    private Letter[] letters;
    /**
     * Oggetto di tipo JMenuItem che identifica la voce Salva Partita dal menu
     */
    private JMenuItem savegame;
    /**
     * Oggetto di tipo SaveGame che identifica il salvataggio di una partita
     */
    private SaveGame save;
    /**
     * Oggetto di tipo Progetto richiamato all'intero della classe
     */
    private Progetto progetto;
    /**
     * Oggetto di tipo GamePanel richiamato all'interno della classe
     */
    private GamePanel gamepanel;
    /**
     * Inizializza un nuovo oggetto CenterPanel, prendendo come parametri di input la manche,
     *  la lista delle frasi lette dal file xml con i relativi suggerimenti, e un oggetto di tipo Progetto
     * @param manche intero che identifica la manche in corso
     * @param phrases Lista contenente le frasi e i suggerimenti
     * @param progetto Oggetto contenente la classe Progetto
     */
    public CenterPanel(int manche, List <Phrase> phrases,Progetto progetto){
        this.manche=manche;
        this.phrasesList=phrases;
        this.progetto=progetto;
        // carica il metodo Layout che imposta il layout del pannello
        setLayout();
        
    }
    /**
     * Restituisce un oggetto di tipo JPanel che identifica il pannello dell'inserimento
     * della risposta. Al suo interno vengono settati i parametri per ottenere l'inserimento
     * di un input testuale da tastiera che identifica la risposta, e la conferma di tale risposta
     * attraveso un pulsante 
     * @return un Oggetto di tipo JPanel contenente il form di risposta
     */
     private JPanel AnswerPanel() {
        
        JPanel jp = new JPanel();
        //Imposta il bordo del pannello
        jp.setBorder(new LineBorder(Color.LIGHT_GRAY, 1, true));
       
        // crea l'input testuale
        answerField= new JTextField(30);
   
        // Inizializza il pulsante per l'invio della risposta
       answerButton= new JButton("Ok");
       // Inserisce l'azione al pulsante
          answerButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
            
                answerButton_actionPerformed(e);
                
            }
        });
        // aggiunge al pannello i 3 elementi
        jp.add(ANSWER);
        jp.add(answerField);
        jp.add(answerButton);
      
        return jp;
    }
     /**
      * Restituisce un oggetto di tipo JPanel che identifica il pannello contenente
      * la frase nascosta. Al suo interno sono presenti una lista di JLabel che identificano
      * ogni singolo carattere della frase
      * @return un JPanel che mostra il pannello della frase nascosta
      */
      private JPanel CPanel() {
        
        JPanel jp = new JPanel();
      
        jp.repaint();
        // inizializza una lista di JPanel 
  jplist = new ArrayList<JPanel>();
  // pulisce la lista
        jplist.clear();
        // imposta il bordo
         jp.setBorder(new LineBorder(Color.LIGHT_GRAY, 1, true));
      // imposta la dimensione
        jp.setPreferredSize(new Dimension(600, 475));
       // metodo che richiama la frase e il relativo suggerimento per poi essere inserito
        // e mostrato nel pannello
         setPhrases(phrasesList.get(manche).getText(),phrasesList.get(manche).getHint());
       
          Font font = new Font("Default", Font.TRUETYPE_FONT,40);
          int count=0;
        for(int i =0; i<phrases.size();i++){
            jplist.add(new JPanel());
            
            phrases.get(i).setFont(font);
             if (!phrases.get(i).getText().equals(" ")&&!phrases.get(i).getText().equals("!")&&
             !phrases.get(i).getText().equals(",")&&!phrases.get(i).getText().equals(";")&&
             !phrases.get(i).getText().equals(".")&&!phrases.get(i).getText().equals("?")&&
             !phrases.get(i).getText().equals("'")&&!phrases.get(i).getText().equals(":")){
           phrases.get(i).setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
           phrases.get(i).setPreferredSize(new Dimension(40,50));
           jplist.get(count).add(phrases.get(i));
           jp.add(jplist.get(count));
           
             }else{
                count++;
          
                
                jp.add(phrases.get(i));
             }
            
             
        }
       
        HidePhrases();
    
        return jp;
    }
      /**
       * Restituisce un oggetto di tipo JPanel che identifica il pannello dei suggerimenti
       * @return un oggetto di tipo JPanel contenente il suggerimento della frase
       */
       private JPanel HintPanel() {
        
        JPanel jp = new JPanel();
         jp.setBorder(new LineBorder(Color.LIGHT_GRAY, 1, true));
          JLabel hint= new JLabel("Suggerimento:");
           JLabel Jhint= new JLabel(hintString);
          jp.add(hint);
          jp.add(Jhint);
      
        return jp;
    }
       /**
        * Aggiunge i vari componenti che costituiscono il pannello CenterPanel
        */
       private void addPanel(){
           // prima di inserire i pannelli rimuove tutti i componenti gia presenti
           // all'interno del pannello CenterPanel
           this.removeAll();
            this.add(AnswerPanel());
        this.add(CPanel());
        this.add(HintPanel());
     
       }
       /**
        * Imposta il Layout del pannello CenterPanel
        */
 private void setLayout() {
       
        layout = new BoxLayout(this, BoxLayout.Y_AXIS);
        this.setLayout(layout);
     
        addPanel();
  
    }
 /**
  * Imposta la frase e il relativo suggerimento dai parametri di input
  * @param text Stringa che identifica la frase nascosta
  * @param hint Stringa che identifica il suggerimento
  */
 private void setPhrases(String text,String hint){
     
  
      hidephrase= text;
      hintString=hint;
     hidephrase=hidephrase.toUpperCase();
     phrasesChar.clear();
     phrases.clear();
     // viene creato un array di stringhe che suddivide la frase in singole parole
     phrasesString=hidephrase.split(" ");
     // scorre l'array delle parole per poter suddividere la parola in caratteri
     // ed aggiunge i caratteri in una lista di caratteri, e in una lista di JLabel
     for(int i =0;i<phrasesString.length;i++){
         for(int j=0;j<phrasesString[i].length();j++){
             phrasesChar.add(phrasesString[i].charAt(j));
        phrases.add( new JLabel(""+phrasesString[i].charAt(j),JLabel.CENTER));
         
         }
         if(i!=phrasesString.length-1)
          phrasesChar.add(' ');
         phrases.add( new JLabel(" "));
     }
  
 }
/**
 * Nasconde i singoli caratteri prenseti all'interno della lista JLabel, ad eccezione
 * dei caratteri speciali '!',' ',',',';','.','?',''',':'
 */
 private void HidePhrases(){
      for(int i =0;i<phrases.size();i++){
            if (!phrases.get(i).getText().equals(" ")&&!phrases.get(i).getText().equals("!")&&
             !phrases.get(i).getText().equals(",")&&!phrases.get(i).getText().equals(";")&&
             !phrases.get(i).getText().equals(".")&&!phrases.get(i).getText().equals("?")&&
              !phrases.get(i).getText().equals("'")&&!phrases.get(i).getText().equals(":")){
             
                phrases.get(i).setText(" ");
            }
      }
 }
 /**
  * Restituisce una Lista di Character contenente i singoli caratteri della frase
  * @return lista di caratteri della frase
  */
 public List<Character> getCharPhrases(){
     return phrasesChar;
 }
 /**
  * Restituisce una lista di JLabel contenente il componente grafico del carattere
  * della frase nascosta
  * @return una lista di JLabel che identificano i caratteri della frase
  */
 public List<JLabel> getPhrases(){
     return phrases;
 }
 /**
  * Imposta l'azione alla voce Salva Parita del menu a tendina
  */
 private void initializeSaveGame(){
     savegame.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
               SaveGame_actionPerformed(e);
                
            }

           
        });
 }
 /**
  * Imposta l'azione del pulsante per l'invio della risposta
  * @param e ActionEvent del pulsante
  */
 private void answerButton_actionPerformed(ActionEvent e) {
     //  inserisce il valore letto dal form di input testuale in una stringa
       answer = answerField.getText();
     
        int player=0;
        // controlla che la frase inserita sia uguale alla frase da indovinare
       if(answer.toUpperCase().equals(hidephrase)){
           // se la condizione è verificata, vengono scoperte tutte le lettere
           for(int i=0; i<phrases.size()-1;i++){
           phrases.get(i).setText(""+hidephrase.charAt(i));
           }
          // si passa alla manche successiva
           manche++;
          // scorre la lista dei giocatori per selezionare il giocatore di turno in quell'istante
           for(int i=0; i<players.size();i++){
               if(players.get(i).isSelected()){
                    // Aggiunge al punteggio partita il punteggio della manche appena vinta
                   players.get(i).setGamePoint(players.get(i).getGamePoint()+players.get(i).getManchePoint());
                
                   
                player = i;
                
               }
               
                
           }
           // controllo per determinare se il gioco è finito. Se la condizione
           // è verificata viene selezionato il giocatore con il punteggio più alto
           // e viene mostrato a video tramite un JOptionPane la sua vittoria
           if(manche>phrasesList.size()-1){
               int max=0;
                  for(int i=0; i<players.size();i++){
                      
               if(players.get(i).getGamePoint()>max){
                   max=players.get(i).getGamePoint();
                   player=i;
               }
             
                  }
                JOptionPane.showMessageDialog(this,players.get(player).getPlayerName() +" vince la Partita");
                answerButton.setEnabled(false);
                // viene ricominciato automaticamente il gioco
                progetto.newGame();
                
          }else{
               //condizione di vittoria della manche
               JOptionPane.showMessageDialog(this, "Risposta esatta. "+ players.get(player).getPlayerName()+" vince la Manche");
           // viene salvato il numero di manche all'intero dell'oggetto SaveGame
           save.setGame(manche);
           // Richiama il metodo che ripulisce la lista che contiene le lettere scoperte in quel momento
           save.clearPhrases();
           // resetta i jolly di ogni giocatore  
           resetJollyManche();
           // resetta lo stato dei pulsanti lettera
             resetLetters();
             // richiama il metodo per il refresh dei pannelli
             addPanel();
             
             this.updateUI();
         
          }
        
   
       }else{
            // Mostra a video l'inserimento di una risposta sbagliata
           JOptionPane.showMessageDialog(this, "Risposta sbagliata");
           // il punteggio di manche del giocatore viene resettato
           players.get(gamepanel.getPlayer()).setManchePoint(0);
//        // il turno passa al giocatore successivo
           gamepanel.nextPlayer();
           // vengono disabilitate le lettere
           gamepanel.DisableLetter();
           // viene abilitato il pulsante Gira
           gamepanel.setWheelButton(true);
       }
       
       
       // cancella l'input testuale della risposta
       answerField.setText("");
    }
 /**
  * Imposta l'azione della voce Salva Partita dal menu a tendina
  * @param e ActionEvent della voce Salva Partita
  */
  private void SaveGame_actionPerformed(ActionEvent e) {
      
    
        // imposta i giocatori all'interno dell'oggetto SaveGame
      save.setPlayers(players);
      // Richiama il metodo per la scrittura del file xml
      save.writeXML();

  }
  /**
   * Imposta allo stato iniziale i pulsanti lettera
   */
 private void resetLetters(){
     for(int i=0;i<letters.length;i++){
         letters[i].setActive(true);
         letters[i].setEnabled(false);
     }
 }
/**
 * Imposta allo stato iniziale il jolly e il punteggio di manche di ogni
 * singolo giocatore
 */
 private void resetJollyManche(){
     for(int i=0;i<players.size();i++){
         players.get(i).setJollyBoolean(false);
         players.get(i).setManchePoint(0);
     }
 }
 /**
  * Imposta la lista di tipo Player che identifica i giocatori
  * @param players Lista di tipo Player che identifica i giocatori
  */
 public void setPlayers(List <Player> players){
     this.players=players;
 }
/**
 * Imposta il valore numerico che identifica la manche
 * @param manche intero che identifica il numero di manche
 */
  public void setManche(int manche){
     this.manche=manche;
 }
  /**
   * Imposta una lista di tipo Phrase contenente le frasi nascoste ed i suggerimenti
   * @param phrases Lista di tipo Phrase con le frasi nascoste e i suggerimenti
   */
   public void setPhrases(List <Phrase> phrases){
       this.phrasesList=phrases;
   }
   /**
    * Imposta un array di tipo Letter che identifica i pulsanti lettera
    * @param letters Array di Letter che identifica i pulsanti lettera
    */
 public void setLetters(Letter [] letters){
     this.letters=letters;
 }
 /**
  * Imposta i componenti per il salvataggio di una partita
  * @param savegame JMenuItem contenente la voce Salva Partita dal menu a tendina
  * @param save SaveGame per il salvataggio del file su un documento xml
  */
 public void setSaveGame(JMenuItem savegame,SaveGame save){
     
     this.savegame=savegame;
     this.save=save;

     initializeSaveGame();
 }
 /**
  * Restituisce il numero di manche che si sta giocando
  * @return
  */
 public int getMancheGame(){
     return manche;
 }
 /**
  * Imposta un oggetto di tipo GamePanel
  * @param gamepanel oggetto di tipo GamePanel
  */
public void setGamePanel(GamePanel gamepanel){
    this.gamepanel=gamepanel;
}
/**
 * Carica da un parametro Array di tipo String, le lettere memorizzate dal file xml
 * per poter ricostruire la frase con le lettere già giocate
 * @param letters Array di tipo String contenente le lettere già giocate
 */
 public void loadLetters(String [] letters){
     for(int i=0; i<letters.length;i++){
     for(int j=0; j<phrases.size()-1;j++){
        
         if(phrasesChar.get(j).toString().equals(letters[i]))
           phrases.get(j).setText(letters[i]);
           }
 }
 }
}

